/**
 * 
 */
package com.vanstone.imgapp.img.services.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import com.vanstone.common.ObjectDuplicateException;
import com.vanstone.common.debug.MyAssert;
import com.vanstone.common.util.PinyinStringUtil;
import com.vanstone.fs.FSManager;
import com.vanstone.fs.api.FileException;
import com.vanstone.fs.api.FileType;
import com.vanstone.fs.local.LocalFSFile;
import com.vanstone.fs.weedfs.WeedFSFile;
import com.vanstone.imgapp.api.img.Category;
import com.vanstone.imgapp.api.img.services.CategoryService;
import com.vanstone.imgapp.common.id.SystemIDSchema;
import com.vanstone.imgapp.common.id.services.IDService;
import com.vanstone.imgapp.img.dal.object.CmsCategoryDO;

/**
 * @author shipeng
 *
 */
@Service("categoryService")
public class CategoryServiceImpl implements CategoryService {

  @Autowired
  private MongoTemplate mongoTemplate;
  @Autowired
  private IDService idService;

  /*
   * (non-Javadoc)
   * 
   * @see com.vanstone.imgapp.api.img.services.CategoryService#addCategory(java.lang.String,
   * java.lang.String, java.lang.String, com.vanstone.fs.local.LocalFSFile)
   */
  @Override
  public synchronized Category addCategory(String categoryName, String categoryNamePinyin, String content, LocalFSFile localImgFSFile) throws ObjectDuplicateException, FileException {
    Query query = Query.query(Criteria.where("categoryName").is(categoryName));
    CmsCategoryDO load_cms_categorydo = this.mongoTemplate.findOne(query, CmsCategoryDO.class);
    if (load_cms_categorydo != null) {
      throw new ObjectDuplicateException();
    }
    if (localImgFSFile != null && !localImgFSFile.getFileType().equals(FileType.Image)) {
      throw new FileException("not img file.");
    }
    WeedFSFile coverFile = null;
    if (localImgFSFile != null) {
      coverFile = FSManager.getInstance().uploadToWeedFS(localImgFSFile.getFile());
    }
    Category category = new Category();
    category.setCategoryName(categoryName);
    category.setCategoryNamePinyin(categoryNamePinyin == null || categoryNamePinyin.equals("") ? PinyinStringUtil.parseInitialLetters(categoryName) : categoryNamePinyin);
    category.setContent(content);
    category.setId(idService.nextID(SystemIDSchema.Cms_Category));
    category.setCoverFile(coverFile);
    load_cms_categorydo = BeanUtil.toCmsCategoryDO(category);
    mongoTemplate.insert(load_cms_categorydo);
    return category;
  }

  @Override
  public void updateBaseCategoryInfo(long id, String categoryName, String categoryNamePinyin, String content) {
    CmsCategoryDO cmsCategoryDO = new CmsCategoryDO();
    cmsCategoryDO.setId(id);
    cmsCategoryDO.setCategoryName(categoryName);
    cmsCategoryDO.setCategoryNamePinyin(categoryNamePinyin);
    cmsCategoryDO.setContent(content);

    Query query = Query.query(Criteria.where("_id").is(id));
    Update update = new Update();
    update.set("categoryName", categoryName);
    update.set("categoryNamePinyin", categoryNamePinyin);
    update.set("content", content);
    this.mongoTemplate.updateFirst(query, update, CmsCategoryDO.class);
  }

  @Override
  public void updateCategoryCoverFileInfo(long id, LocalFSFile localImgFSFile) throws FileException {
    if (!localImgFSFile.getFileType().equals(FileType.Image)) {
      throw new FileException();
    }
    Category category = this.getCategory(id);
    MyAssert.objectInitialized(category);
    WeedFSFile weedFSFile = FSManager.getInstance().uploadToWeedFS(localImgFSFile.getFile());
    WeedFSFile temp_weedfsfile = category.getCoverFile();
    Query query = Query.query(Criteria.where("_id").is(id));
    Update update = new Update();
    update.set("coverFile", weedFSFile);
    this.mongoTemplate.updateFirst(query, update, CmsCategoryDO.class);
    if (temp_weedfsfile != null) {
      temp_weedfsfile.delete();
    }
  }

  @Override
  public Category getCategory(long id) {
    CmsCategoryDO cmsCategoryDO = this.mongoTemplate.findById(id, CmsCategoryDO.class);
    if (cmsCategoryDO == null) {
      return null;
    }
    return BeanUtil.toCategory(cmsCategoryDO);
  }

  @Override
  public Category getCategoryByName(String categoryName) {
    MyAssert.hasText(categoryName);
    Query query = new Query(Criteria.where("categoryName").is(categoryName));
    CmsCategoryDO cmsCategoryDO = this.mongoTemplate.findOne(query, CmsCategoryDO.class);
    if (cmsCategoryDO == null) {
      return null;
    }
    return BeanUtil.toCategory(cmsCategoryDO);
  }

  @Override
  public List<Category> getCategories(long offset, long limit) {
    Query query = new Query();
    query.skip((int) offset);
    query.limit((int) limit);
    query.with(new Sort(Direction.DESC, "imgcount"));
    List<CmsCategoryDO> cmsCategoryDOs = this.mongoTemplate.find(query, CmsCategoryDO.class);
    if (cmsCategoryDOs == null || cmsCategoryDOs.size() <= 0) {
      return null;
    }
    List<Category> categories = new ArrayList<>();
    for (CmsCategoryDO cmsCategoryDO : cmsCategoryDOs) {
      categories.add(BeanUtil.toCategory(cmsCategoryDO));
    }
    return categories;
  }

  @Override
  public long getTotalCategories() {
    Query query = new Query();
    return this.mongoTemplate.count(query, CmsCategoryDO.class);
  }

  @Override
  public Map<Long, Category> getCategoriesByIDsAsMap(List<Long> ids) {
    Map<Long, Category> map = new HashMap<>();
    if (ids == null || ids.size() <= 0) {
      return map;
    }
    Criteria criteria = Criteria.where("id").in(ids);
    Query query = new Query(criteria);
    List<CmsCategoryDO> cmsCategoryDOs = this.mongoTemplate.find(query, CmsCategoryDO.class);
    if (cmsCategoryDOs == null || cmsCategoryDOs.size() <= 0) {
      return map;
    }
    for (CmsCategoryDO cmsCategoryDO : cmsCategoryDOs) {
      Category category = BeanUtil.toCategory(cmsCategoryDO);
      map.put(category.getId(), category);
    }
    return map;
  }

  @Override
  public List<Category> getCategoriesByIDs(List<Long> ids) {
    List<Category> categories = new ArrayList<>();
    categories.addAll(this.getCategoriesByIDsAsMap(ids).values());
    return categories;
  }

}
